package blyth;

import java.awt.Point;

public class ExploreTask extends Task {
    
    public boolean reached;
    public boolean lastRoundWaited; // For exploring "light" if we already know one food

    public ExploreTask(World world, Point goal) {
        super(world, 1, goal);
        this.reached = false;
        this.lastRoundWaited = false;
    }

    @Override
    public boolean IsValid() {
        // we never throw an explore task, just change it's goal from outside
        return true;
    }

    @Override
    public int AvailabilityFrom(Agent agent) {
        // Not used, explore task won't be "generated"
        return 0;
    }

    @Override
    public Command Solve() {
        // We already know all the food, no need for exploring
        if (world.Foods.size() >= World.maxFoods) {
            // Also no need for checking
            World.turnsSinceLastFoodAction = 0;
            return new Command(Command.Action.Wait, 0, 0);
        }
        // We know one food, keep exploring "light"
        if (world.Foods.size() == 1) {
            lastRoundWaited = !lastRoundWaited;
            if (lastRoundWaited == false) {
                // Disabled, not really useful
                //return new Command(Command.Action.Wait, 0, 0);
            }            
        }
        // Check reached state
        if (Heur.Bird(goal, assignedTo.position) > 1) {
            reached = false;
        }
        // We can't get to destination because of enemy
        Agent enemy = world.GetEnemy(goal);
        if (enemy != null && Heur.Bird(assignedTo.position, goal) == 1
                && assignedTo.CanSee(enemy.position)) {
            // Are we in water?
            if (assignedTo.inWater == false) {
                // Consider attacking
                if (assignedTo.energy > enemy.energy + 4000 &&
                        Heur.Manhattan(goal, world.AttackResult(assignedTo, enemy.position)) > 2) {
                    return new Command(Command.Action.Attack, enemy.id, 0);
                } else {
                    // we have less energy, and we are not in water -> we stay here
                    reached = true;
                    return ExploreTurn();
                }
            } else {
                // We are in water, we shouldn't stay here
                for (WorldIterator it = new WorldIterator(world, goal.x, goal.y, 1,
                        false, 1); it.IsNotEnd(); it.Next()) {
                    if (it.Get().isWater == false && world.IsThereEnemy(new Point(it.x,it.y)) == false) {
                        // We move our goal, to a next water and agent-free tile
                        goal.setLocation(it.x, it.y);
                        return world.Approach(assignedTo, goal);
                    }
                }
            }
        } else if (assignedTo.position.equals(goal) || reached) {
            // We are at goal
            reached = true;
            return ExploreTurn();
        }
        return world.Approach(assignedTo, goal);
    }

    private Command ExploreTurn() {
        // Adjusting turn speed
        if (assignedTo.turnsMade < 4 && assignedTo.shouldWait > 0) {
            assignedTo.shouldWait = 0;
        } else if (assignedTo.turnsMade >= 4 && assignedTo.shouldWait == 0) {
            assignedTo.shouldWait = 2;
        } else if (assignedTo.turnsMade >= 8 && assignedTo.shouldWait <= 2) {
            assignedTo.shouldWait = 5;
        }
        // Should we turn or wait?
        if (assignedTo.waited < assignedTo.shouldWait) {
            assignedTo.waited++;
            return new Command(Command.Action.Wait, 0, 0);
        } else {
            assignedTo.waited = 0;
            assignedTo.turnsMade++;
            int newdir = assignedTo.direction + 1;
            if (newdir > 3) {
                newdir = 0;
            }
            return new Command(Command.Action.Turn, newdir, 0);
        }
    }
}